package com.kurumi.autoprint.util;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.UUID;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.net.ssl.SSLContext;
import javax.net.ssl.X509TrustManager;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.kurumi.autoprint.pojo.pay.PayUmsTidBindIp;

/**
 * @author zhangjz
 * @date 2019/6/3
 */
public class PayUtil {
	private static Logger logger = LoggerFactory.getLogger(PayUtil.class); // 日志记录
	private static RequestConfig requestConfig = null;
	static {
		// 设置请求和传输超时时间
		requestConfig = RequestConfig.custom().setSocketTimeout(10000).setConnectTimeout(10000).build();
	}

	public static String send(String url, String entity, String appId, String appKey) {
		CloseableHttpResponse response = null;
		String resStr = null;
		CloseableHttpClient httpClient = null;
		if (isHttps(url)) {
			httpClient = HttpClients.custom().setSslcontext(generateSSLContext()).build();
		} else {
			httpClient = HttpClients.createDefault();
		}
		try {
			String authorization = getOpenBodySig(appId, appKey, entity);
			HttpPost httpPost = new HttpPost(url);
			httpPost.setConfig(requestConfig);
			httpPost.addHeader("Authorization", authorization);
			httpPost.setHeader("Content-type", "application/json; charset=utf-8");
			StringEntity se = new StringEntity(entity, "UTF-8");
			se.setContentType("application/json");
			httpPost.setEntity(se);
			response = httpClient.execute(httpPost);
			HttpEntity entity1 = response.getEntity();
			resStr = null;
			if (entity1 != null) {
				resStr = EntityUtils.toString(entity1, "UTF-8");
			}
		} catch (Exception e) {
			logger.error("post请求提交失败:url{}，参数{}", url, entity, e);
			return null;
		} finally {
			if (response != null) {
				try {
					httpClient.close();
					response.close();
				} catch (IOException e) {
					logger.info("链接释放失败", e);
				}
			}
		}
		return resStr;
	}

	public static void main(String[] args) {

	}

	public static String getOpenBodySig(String appId, String appKey, String body) throws Exception {
		String timestamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
		String nonce = UUID.randomUUID().toString().replace("-", "");
		byte[] data = body.getBytes("UTF-8");
//        System.out.println("data:\n" + body);
		InputStream is = new ByteArrayInputStream(data);
		String bodyDigest = testSHA256(is);
		String str1_C = appId + timestamp + nonce + bodyDigest;

		byte[] localSignature = hmacSHA256(str1_C.getBytes(), appKey.getBytes());

		String localSignatureStr = Base64.encodeBase64String(localSignature);
		logger.info(
				"Authorization:\n" + "OPEN-BODY-SIG AppId=" + "\"" + appId + "\"" + ", Timestamp=" + "\"" + timestamp
						+ "\"" + ", Nonce=" + "\"" + nonce + "\"" + ", Signature=" + "\"" + localSignatureStr + "\"");
		return ("OPEN-BODY-SIG AppId=" + "\"" + appId + "\"" + ", Timestamp=" + "\"" + timestamp + "\"" + ", Nonce="
				+ "\"" + nonce + "\"" + ", Signature=" + "\"" + localSignatureStr + "\"");
	}

	private static String testSHA256(InputStream is) {
		try {
			return DigestUtils.sha256Hex(is);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

	public static byte[] hmacSHA256(byte[] data, byte[] key) throws NoSuchAlgorithmException, InvalidKeyException {
		String algorithm = "HmacSHA256";
		Mac mac = Mac.getInstance(algorithm);
		mac.init(new SecretKeySpec(key, algorithm));
		return mac.doFinal(data);
	}

	/**
	 * 检测是否https
	 *
	 * @param url
	 */
	private static boolean isHttps(String url) {
		return url.startsWith("https");
	}

	/* 为了访问https接口 */
	private static SSLContext generateSSLContext() {
		SSLContext sslContext = null;
		try {
			sslContext = SSLContext.getInstance("TLS");
			sslContext.init(null, new X509TrustManager[] { new X509TrustManager() {
				@Override
				public void checkClientTrusted(X509Certificate[] x509Certificates, String s)
						throws CertificateException {
				}

				@Override
				public void checkServerTrusted(X509Certificate[] x509Certificates, String s)
						throws CertificateException {
				}

				@Override
				public X509Certificate[] getAcceptedIssuers() {
					return new X509Certificate[0];
				}
			} }, null);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (KeyManagementException e) {
			e.printStackTrace();
		}
		return sslContext;
	}

	public static String getTidByClientIp(String ip, String defaultTid, String fileName) {
		if (StringUtil.isBlank(ip)) {
			return defaultTid;
		}

		String jsonStr = FileUtil.readResourceFile(fileName);

		if (StringUtil.isBlank(jsonStr)) {
			logger.error("读取本地payUmsTidBindIp.json文件读取不到信息--");
			return defaultTid;
		}

		try {
			List<PayUmsTidBindIp> list = JsonUtil.jsonToList(jsonStr, PayUmsTidBindIp.class);

			for (PayUmsTidBindIp obj : list) {
				if (StringUtils.isNotBlank(obj.getIp()) && obj.getIp().trim().equalsIgnoreCase(ip)) {
					String tid = obj.getTid().trim();

					if (StringUtil.isNotBlank(tid)) {
						return tid;
					}
				}
			}
		} catch (Exception e) {
			logger.error("--读取本地payUmsTidBindIp转成list对象异常---" + ExceptionUtil.getStackTrace(e));
			return defaultTid;
		}

		return defaultTid;

	}

	/**
	 * 获取打印机IP
	 * @param ip
	 * @param fileName
	 * @return
	 */
	public static String getPrintMachineIpByClientIp(String ip, String fileName) {

		String jsonStr = FileUtil.readResourceFile(fileName);

		if (StringUtil.isBlank(jsonStr)) {
			logger.error("读取本地payUmsTidBindIp.json文件读取不到信息--");
			return null;
		}

		try {
			List<PayUmsTidBindIp> list = JsonUtil.jsonToList(jsonStr, PayUmsTidBindIp.class);

			for (PayUmsTidBindIp obj : list) {
				if (StringUtils.isNotBlank(obj.getIp()) && obj.getIp().trim().equals(ip)) {
					return obj.getPrintMachineIp().trim();

				}
			}
		} catch (Exception e) {
			logger.error("--读取本地payUmsTidBindIp转成list对象异常---" + ExceptionUtil.getStackTrace(e));
			return null;
		}

		return null;

	}

	/**
	 * 获取打印机型号
	 * 
	 * @param ip
	 * @param fileName
	 * @return
	 */
	public static String getPrinterNameByClientIp(String ip, String fileName) {

		String jsonStr = FileUtil.readResourceFile(fileName);

		if (StringUtil.isBlank(jsonStr)) {
			logger.error("读取本地payUmsTidBindIp.json文件读取不到信息--");
			return null;
		}

		try {
			List<PayUmsTidBindIp> list = JsonUtil.jsonToList(jsonStr, PayUmsTidBindIp.class);

			for (PayUmsTidBindIp obj : list) {
				if (StringUtils.isNotBlank(obj.getIp()) && obj.getIp().trim().equals(ip)) {
					return obj.getPrinterName().trim();

				}
			}
		} catch (Exception e) {
			logger.error("--读取本地payUmsTidBindIp转成list对象异常---" + ExceptionUtil.getStackTrace(e));
			return null;
		}

		return null;

	}

}